(*******************************************************************
This file was generated automatically by the Mathematica front end.
It contains Initialization cells from a Notebook file, which
typically will have the same name as this file except ending in
".nb" instead of ".m".

This file is intended to be loaded into the Mathematica kernel using
the package loading commands Get or Needs.  Doing so is equivalent
to using the Evaluate Initialization Cells menu command in the front
end.

DO NOT EDIT THIS FILE.  This entire file is regenerated
automatically each time the parent Notebook file is saved in the
Mathematica front end.  Any changes you make to this file will be
overwritten.
***********************************************************************)

BeginPackage["PBRT`Export`"]

PBRTExport::usage="PBRTExport[file, graphics, options] writes 3D graphics to a file in PBRT
format and returns the filename.
PBRTExport[graphics,options] opens a temporary file, writes to that file, and
returns the file name."
EXRWidth::usage = "Gives the width of the output image."

EXRHeight::usage = "Gives the width of the output image."
EXRFile::usage = "Gives the name of the output image."

GeometryOnly::usage = "Only write out geometry, not a full scene."

VertexNormals::usage = "Output smooth normals for function plots."

TextureWarp::usage = "Distortion function for texture coordinates."


Begin["`Private`"]

PBRT::nodata = "Hmm -- couldn't find the bounding box.  Is there data?"

Options[PBRTExport]={EXRWidth\[Rule]512,EXRHeight\[Rule]384,
    GeometryOnly\[Rule]False,VertexNormals\[Rule]True,TextureWarp\[Rule](#&)}

PBRTExport[g_,opts___]:=Block[{stm},stm=OpenTemporary[];
    PBRTExport[stm,g,opts,EXRFile\[Rule]"mathematica.exr"];
    Close[stm]]


PBRTExport[file_String,g_,opts___]:=Block[{stm,outfile,slashes},
    stm=OpenWrite[file];
    outfile="mathematica.exr";
    If[StringLength[file]\[GreaterEqual]StringLength[".pbrt"],
      If[StringTake[file,-5]\[Equal] ".pbrt",
        (
          outfile =StringDrop[file,-5]<>".exr" ;
          slashes = StringPosition[outfile,"/"];
          
          If[Length[slashes]>0,
            outfile = StringTake[outfile,{Last[slashes][[1]]+1,-1}]]
          )]
      ];
    PBRTExport[stm,g,opts,EXRFile\[Rule]outfile];
    Close[stm]]



PBRTExport[stream_OutputStream,gg:Graphics3D[g_,___],opts___]:=
  
  Block[{w,h,go,allopts,bounds,min,max,sceneMin,sceneMax,sceneCenter,up,
      sceneUp,outfile},(
      {w,h,go,out}={EXRWidth,EXRHeight,GeometryOnly,EXRFile}/.{opts} /. 
          Options[PBRTExport];
      bounds = PBRTBounding[stream,g];
      If [bounds \[Equal] False, Return[]];
      {min,max} = bounds;
      If [!go,PBRTHeader[stream,w,h,out,bounds,gg,opts]];
      PBRTWriteGeometry[stream,g];
      If[!go,PBRTFooter[stream]];
      StreamToFile[stream])
    ]

PBRTHeader[stream_OutputStream,w_,h_,out_,{min_,max_},gg_Graphics3D,
    opts___] :=
  (
    WriteName[stream,"# PBRT File generated automatically from Mathematica"];
    WriteName[stream,"# Bounding Box"];
    WriteName[stream, "# min: " <> ToString[min]];
    WriteName[stream, "# max: " <> ToString[max]];
    WriteFilm[stream,w,h,out];
    sceneMin = min /. {opts} /. Options[gg] /. Options[Graphics3D];
    sceneMax = max /. {opts} /. Options[gg] /. Options[Graphics3D];
    sceneCenter = (sceneMin + sceneMax)/2;
    WriteCamera[stream,
      ViewPoint/.{opts} /. Options[gg] /. Options[Graphics3D], sceneCenter, 
      ViewVertical /. {opts} /. Options[gg] /. Options[Graphics3D], sceneMin, 
      sceneMax];
    WriteName[stream,"WorldBegin"];
    If[Lighting/.{opts} /. Options[gg] /. Options[Graphics3D],
      WriteLightSources[stream,
          LightSources/.{opts} /. Options[gg] /. Options[Graphics3D]];]
    )

PBRTFooter[stream_OutputStream] :=
    WriteName[stream,"WorldEnd"];

PBRTBounding[file_,g_]:=
  Block[{min,max,mini,maxi},mini=min={Infinity,Infinity,Infinity};
    maxi=max=-min;
    Scan[PBRTBounding0[#,min,max]&,Flatten[{g}]];
    If[min\[Equal]mini||max\[Equal]maxi,Message[PBRT::nodata]; 
      Return[False]];
    
    Return[{min,max}]]

SetAttributes[{PBRTBounding0,PBRTBounding1},HoldRest]


PBRTBounding0[Polygon[g_List],min_,max_]:=Scan[PBRTBounding1[#,min,max]&,g]


PBRTBounding0[Line[g_List],min_,max_]:=Scan[PBRTBounding1[#,min,max]&,g]


PBRTBounding0[Point[g_List],min_,max_]:=PBRTBounding1[g,min,max]


PBRTBounding0[Cuboid[g_List],min_,max_]:=(PBRTBounding1[g,min,max];
    PBRTBounding1[g+{1,1,1},min,max])


PBRTBounding0[Cuboid[g_List,h_List],min_,max_]:=(PBRTBounding1[g,min,max];
    PBRTBounding1[h,min,max])


PBRTBounding1[l:{_,_,_},min,max]:=(min=Map[Min,Transpose[{l,min}]];
    max=Map[Max,Transpose[{l,max}]];)


WriteFilm[file_,w_, h_,out_String] := (
    WriteName[file,
      "Film \"image\" \"integer xresolution\" [" <>  ToString[N[w]] <> 
        "] \"integer yresolution\" [" <> ToString[N[h]] <> 
        "]\n     \"string filename\" \"" <>out <> "\""])



WriteCamera[file_,eye:{_,_,_},center:{_,_,_},up:{_,_,_}, min_, max_]:=
  
  Block[{eyepoint},
    (eyepoint =ComputeEyePoint[eye, center, min, max] //N;
      WriteNameStr[file,"LookAt "];
      WriteTripleStr[file,eyepoint];
             WriteNameStr[file," "];
      WriteTripleStr[file,center];
      WriteNameStr[file," "];
      WriteTriple[file,up];
      WriteNameStr[file,"Camera \"perspective\" \"float fov\" ["];
      fov = ComputeFOV[eyepoint,center,min,max];
      WriteNameStr[file,ToString[N[fov*180/Pi]]];
      WriteName[file,"]"]
      )]


ComputeEyePoint[eye:{_,_,_},center:{_,_,_},min:{_,_,_}, max:{_,_,_}] :=
  
  Block[{maxlen},
    (maxlen = 
        Max[Abs[min[[1]]-max[[1]]], Abs[min[[2]]-max[[2]]], 
          Abs[min[[3]]-max[[3]]]];
      Return[center + eye*maxlen])]

ComputeFOV[eye:{_,_,_},center:{_,_,_},min:{_,_,_}, max:{_,_,_}] :=
  
  Block[{look,r,halfAngle},
    (look=eye-center;
      r = (min-max)/2;
      halfAngle = ArcSin[Sqrt[(r.r)/(look.look)]];
      2*halfAngle
      )]

WriteColor[file_,RGBColor[r_,g_,b_]]:=WriteTriple[file,{r,g,b}]

WriteColorStr[file_,RGBColor[r_,g_,b_]]:=WriteTripleStr[file,{r,g,b}]

WriteColor[file_,GrayLevel[x_]]:=WriteTriple[file,{x,x,x}]

WriteColorStr[file_,GrayLevel[x_]]:=WriteTripleStr[file,{x,x,x}]

WriteColor[file_,{x_}]:=WriteColor[file,x]

WriteLightSources[file_,s_List]:=(
    WriteName[file,"# Light Sources"];
    WriteName[file,"AttributeBegin"];
    WriteName[file,"  CoordSysTransform \"camera\""];
    Scan[WriteLS0[file,#]&,s];
    WriteName[file, "AttributeEnd"])

WriteLS0[file_,{dir:{dx_,dy_,dz_},c_}]:=(
    WriteNameStr[file, "  LightSource \"distant\" \"point to\" ["];
    WriteTripleStr[file,{-dx,-dy,dz}];
    WriteNameStr[file, "] \"color L\" ["];
    WriteColorStr[file,c];
    WriteName[file,"]"])

PBRTWriteGeometry[file_,g_List]:=Scan[PBRTWriteGeometry[file,#]&,g]

WriteName[file_,name_String]:=Write[file,TextForm[name]]

WriteNameStr[file_,name_String]:=WriteString[file,TextForm[name]]

PBRTWriteGeometry[file_,Cuboid[g_List]]:=
  PBRTWriteGeometry[file,Cuboid[g,g+{1,1,1}]]

PBRTWriteGeometry[file_,Cuboid[g1_List,h1_List]]:=
  Block[{a,b,c,d,e,f,g,h,rs},a=g1;
    b=CuboidAux[g1,h1,{1,0,0}];
    c=CuboidAux[g1,h1,{1,1,0}];
    d=CuboidAux[g1,h1,{0,1,0}];
    e=CuboidAux[g1,h1,{0,0,1}];
    f=CuboidAux[g1,h1,{1,0,1}];
    g=h1;
    h=CuboidAux[g1,h1,{0,1,1}];
    res={Polygon[{a,b,c,d}],Polygon[{a,b,f,e}],Polygon[{a,d,h,e}],
        Polygon[{b,c,g,f}],Polygon[{e,f,g,h}],Polygon[{d,c,g,h}]};
    PBRTWriteGeometry[file,res]]

CuboidAux[g_List,h_List,vec_List]:=(g ({1,1,1}-vec)+h vec)

PBRTWriteGeometry[file_,Polygon[g_List]]:=(
    WriteName[file,"Shape \"trianglemesh\" \"point P\" ["];
    Scan[(WriteNameStr[file,"  "];WriteTriple[file,#])&,g];
    WriteName[file, "] \"integer indices\" ["];
    Scan[(WriteNameStr[file,"  "];WriteTriple[file,#])&,
      (Prepend[#,0]& /@ Partition[Range[Length[g]-1],2,1])];
    WriteName[file, "]\n"]
    )

PBRTWriteGeometry[file_,vertices_List,normals_List,vertnorms_,warp_] :=
  
  Block[{nu,nv,indices,texturecoords},(
      WriteName[file,"Shape \"trianglemesh\" \"point P\" ["];
      (WriteNameString[file,"  "]; WriteTriple[file,#])& /@ 
        Flatten[vertices,1];
      If[vertnorms,WriteName[file, "] \"normal N\" ["];
        (WriteNameString[file,"  "]; WriteTriple[file,#])& /@ 
          Flatten[normals,1];
        ];
      nu = Length[vertices];
      nv  = Length[vertices[[1]]];
      du = 1/(nu-1);
      dv = 1/(nv-1);
      WriteName[file,"] \"float uv\" ["];
      texturecoords = Table[warp[{x,y}],{y,0,1,dv},{x,0,1,du}];
      Print[texturecoords];
      (WriteNameString[file,"  "]; WritePair[file,#])& /@ 
        Flatten[texturecoords,1];WriteName[file, "] \"integer indices\" ["];
      indices = Join[
          Flatten[
            
            Table[{x+(y+1)*nu,x+1 + y*nu,x+1 + (y+1)*nu},{x,0, nu-2},{y,0,
                nv-2}],1],
          Flatten[
            Table[{x + y*nu,x+1 + y*nu,x+(y+1)*nu},{x,0, nu-2},{y,0,nv-2}],
            1]];
      (WriteNameString[file,"  "]; WriteTriple[file,#])& /@ indices;
      WriteName[file, "]\n"];
      )]

WriteTriple[file_,g:{_,_,_}]:=
  Apply[Write[file,CForm[N[#1]],TextForm[" "],CForm[N[#2]],TextForm[" "],
        CForm[N[#3]]]&,g]

WritePair[file_,g:{_,_}]:=
  Apply[Write[file,CForm[N[#1]],TextForm[" "],CForm[N[#2]]]&,g]

WriteTripleStr[file_,g:{_,_,_}]:=
  Apply[WriteString[file,CForm[N[#1]],TextForm[" "],CForm[N[#2]],
        TextForm[" "],CForm[N[#3]]]&,g]

StreamToFile[stm_OutputStream]:=First[stm]

SurfaceBounding[file_,g_List,{_,_,{zmin_,zmax_}}]:=
  Block[{dim},dim=(zmax-zmin)/0.4;
    WriteName[file,"boundingbox"];
    WriteTriple[file,{0,0,zmin}];
    WriteTriple[file,{dim,dim,zmax}]]

SurfaceBounding[file_,g_List,_Symbol]:=
  SurfaceBounding[file,g,{Apply[Min,Flatten[g]],Apply[Max,Flatten[g]]}]

PBRTExport[stream_OutputStream,gg:SurfaceGraphics[g_,___],opts___]:=
  Block[{w,h,go,min,max,offset,scale,out},
    {w,h,go,
        out}=({EXRWidth,EXRHeight,GeometryOnly,EXRFile}/.{opts})/.Options[
          PBRTExport];
    {min,max} = Transpose[PlotRange[gg]];
    If [!go,PBRTHeader[stream,w,h,out,{min,max},gg,opts]];
    {d1,d2}=Dimensions[g];
    offset = {-.5,-.5,-(max[[3]]-min[[3]])/2};
    scale = { max[[1]]-min[[1]], max[[2]]-min[[2]],4};
    WriteNameStr[stream, "Translate "];
    WriteTriple[stream, -offset];
    WriteNameStr[stream, "Scale "];
    WriteTriple[stream, scale];
    WriteNameStr[stream, "Translate "];
    WriteTriple[stream, offset];
    WriteNameStr[stream, "Shape \"heightfield\" \"integer nu\" ["];
    WriteNameStr[stream, ToString[N[d1]]];
    WriteNameStr[stream,"] \"integer nv\" ["];
    WriteNameStr[stream, ToString[N[d2]]];
    WriteName[stream, "] \"float Pz\" ["];
    Scan[Write[stream,CForm[N[#]]]&,g,{2}];
    WriteName[stream, "]"];
    If[!go,PBRTFooter[stream]];
    StreamToFile[stream]]

PBRTExport[stream_OutputStream, 
    gg:PBRT`SurfaceGraphics3D`SurfaceGraphics3D[verts_,normals_,surfopts_],
    opts___] :=
  
  Block[{w,h,go,allopts,bounds,min,max,sceneMin,sceneMax,sceneCenter,up,
      sceneUp,outfile,convertedG3D},(
      {w,h,go,out,vertnorms,
          warp}={EXRWidth,EXRHeight,GeometryOnly,EXRFile,VertexNormals,
              TextureWarp}/.{opts} /. Options[PBRTExport];
      convertedG3D=Graphics3D[gg];
      bounds = PBRTBounding[stream,convertedG3D[[1]]];
      If [bounds \[Equal] False,Return[]];
      {min,max} = bounds;
      If [!go,PBRTHeader[stream,w,h,out,bounds,convertedG3D,opts]];
      PBRTWriteGeometry[stream,verts,normals,vertnorms,warp];
      If[!go,PBRTFooter[stream]];
      StreamToFile[stream]
      )
    ]

PBRTExport[stream_OutputStream, gg:_PBRT`SurfaceGraphics3D`SurfaceGraphics3D,
    opts___] :=
  PBRTExport[stream,Graphics3D[gg],opts]

End[]

EndPackage[]